package Olivia.olivia3d.model.ms3d
{
	import flash.net.URLStream;
	import flash.utils.ByteArray;

	public class Ms3dStruct
	{
		private var _data:URLStream;
		
		public var head_id:String;					// always "MS3D000000"
		public const head_id_length:int = 10;	
		public var version:int;						// 4
		
		public var nVertices:int;					//short
		public var Vertices:Vector.<MsVertex>;
		
		public var nTriangles:int;					//short
		public var Triangles:Vector.<MsTriangle>;
		
		public var nGroups:int;						//short
		public var Groups:Vector.<MsGroup>;
		
		public var nMaterials:int;					//short
		public var Materials:Vector.<MsMaterial>;
		
		public var fAnimationFPS:Number;			//4 bytes
		public var fCurrentTime:Number;				//4 bytes
		public var iTotalFrames:Number;				//4 bytes
		
		public var nJoints:int;						//short
		public var Joints:Vector.<MsJoint>;
		
		public function Ms3dStruct(dataStream:URLStream)
		{
			_data = dataStream;
			parseStream()
		}
		
		protected function parseStream():void
		{
			head_id = _data.readMultiByte(head_id_length,"us-ascii");
			version = _data.readInt();
			
			nVertices = _data.readShort();
			Vertices = new Vector.<MsVertex>(nVertices);
			for(var i:int=0; i < nVertices; ++i)
			{
				Vertices[i] = parseVectors();
			}
			
			nTriangles = _data.readShort();
			Triangles = new Vector.<MsTriangle>(nTriangles);
			for(var j:int=0; j < nTriangles; ++j)
			{
				Triangles[j] = parseTriangles();
			}
			
			nGroups = _data.readShort();
			Groups = new Vector.<MsGroup>(nGroups);
			for(var k:int=0; k < nGroups; ++k)
			{
				Groups[k] = parseGroups();
			}
			
			nMaterials = _data.readShort();
			Materials = new Vector.<MsMaterial>(nMaterials);
			for(var l:int=0; l < nMaterials; ++l)
			{
				Materials[l] = parseMaterials();
			}
			
			fAnimationFPS = _data.readFloat();
			fCurrentTime = _data.readFloat();
			iTotalFrames = _data.readInt();
			
			nJoints = _data.readShort();
			Joints = new Vector.<MsJoint>(nJoints);
			for(var m:int=0; m < nJoints; ++m)
			{
				Joints[m] = parseJoints();
			}
		}
		
		protected function parseVectors():MsVertex
		{
//			typedef struct
//			{
//				byte    flags;                                      // SELECTED | SELECTED2 | HIDDEN
//				float   vertex[3];                                  //
//				char    boneId;                                     // -1 = no bone
//				byte    referenceCount;
//			} ms3d_vertex_t;
			var flags:int = _data.readByte();
			var x:Number = _data.readFloat();
			var y:Number = _data.readFloat();
			var z:Number = _data.readFloat();
			var boneId:int = _data.readByte();
			var referenceCount:int = _data.readByte();
			
			return new MsVertex(flags,x,y,z,boneId,referenceCount);
		}
		
		protected function parseTriangles():MsTriangle
		{
//			typedef struct
//			{
//				word    flags;                                      // SELECTED | SELECTED2 | HIDDEN
//				word    vertexIndices[3];                           //
//				float   vertexNormals[3][3];                        //
//				float   s[3];                                       //
//				float   t[3];                                       //
//				byte    smoothingGroup;                             // 1 - 32
//				byte    groupIndex;                                 //
//			} ms3d_triangle_t;
			var flags:int = _data.readShort();
			var vertexIndiecs:Array = [_data.readShort(),_data.readShort(),_data.readShort()];
			var vertexNormals:Array = 
				[[_data.readFloat(),_data.readFloat(),_data.readFloat()],
					[_data.readFloat(),_data.readFloat(),_data.readFloat()],
					[_data.readFloat(),_data.readFloat(),_data.readFloat()]];
			var s:Array = [_data.readFloat(),_data.readFloat(),_data.readFloat()];
			var t:Array = [_data.readFloat(),_data.readFloat(),_data.readFloat()];
			var smoothingGroup:int = _data.readByte();
			var groupIndex:int = _data.readByte();
			
			return new MsTriangle(flags,vertexIndiecs,vertexNormals,s,t,smoothingGroup,groupIndex);
		}
		
		protected function parseGroups():MsGroup
		{
//			typedef struct
//			{
//				byte            flags;                              // SELECTED | HIDDEN
//				char            name[32];                           //
//				word            numtriangles;                       //
//				word            triangleIndices[numtriangles];      // the groups group the triangles
//				char            materialIndex;                      // -1 = no material
//			} ms3d_group_t;
			var flags:int = _data.readByte();
			var name:String = _data.readMultiByte(MsGroup.name_length,"us-ascii");
			var numtriangles:int = _data.readShort();
			var triangleIndices:Array = [];
			for(var i:int=0; i < numtriangles; ++i)
			{
				triangleIndices.push(_data.readShort());
			}			
			var materialIndex:int = _data.readByte();
			
			return new MsGroup(flags,name,numtriangles,triangleIndices,materialIndex);
		}
		
		protected function parseMaterials():MsMaterial
		{
//			typedef struct
//			{
//				char            name[32];                           //
//				float           ambient[4];                         //
//				float           diffuse[4];                         //
//				float           specular[4];                        //
//				float           emissive[4];                        //
//				float           shininess;                          // 0.0f - 128.0f
//				float           transparency;                       // 0.0f - 1.0f
//				char            mode;                               // 0, 1, 2 is unused now
//				char            texture[128];                        // texture.bmp
//				char            alphamap[128];                       // alpha.bmp
//			} ms3d_material_t;
			var name:String = _data.readMultiByte(MsMaterial.name_length,"us-ascii");
			var ambient:Array = [_data.readFloat(),_data.readFloat(),_data.readFloat(),_data.readFloat()];
			var diffuse:Array = [_data.readFloat(),_data.readFloat(),_data.readFloat(),_data.readFloat()];
			var specular:Array = [_data.readFloat(),_data.readFloat(),_data.readFloat(),_data.readFloat()];
			var emissive:Array = [_data.readFloat(),_data.readFloat(),_data.readFloat(),_data.readFloat()];
			var shininess:Number = _data.readFloat();
			var transparency:Number = _data.readFloat();
			var mode:int = _data.readByte();
			var texture:String = _data.readMultiByte(MsMaterial.texture_length,"us-ascii");
			var alphamap:String = _data.readMultiByte(MsMaterial.alphamap_length,"us-ascii");
			
			return new MsMaterial(name,ambient,diffuse,specular,emissive,shininess,transparency,mode,texture,alphamap);
		}
		
		protected function parseJoints():MsJoint
		{
//			typedef struct // 16 bytes
//			{
//				float           time;                               // time in seconds
//				float           rotation[3];                        // x, y, z angles
//			} ms3d_keyframe_rot_t;
//			
//			typedef struct // 16 bytes
//			{
//				float           time;                               // time in seconds
//				float           position[3];                        // local position
//			} ms3d_keyframe_pos_t;
//			
//			typedef struct
//			{
//				byte            flags;                              // SELECTED | DIRTY
//				char            name[32];                           //
//				char            parentName[32];                     //
//				float           rotation[3];                        // local reference matrix
//				float           position[3];
//				
//				word            numKeyFramesRot;                    //
//				word            numKeyFramesTrans;                  //
//				
//				ms3d_keyframe_rot_t keyFramesRot[numKeyFramesRot];      // local animation matrices
//				ms3d_keyframe_pos_t keyFramesTrans[numKeyFramesTrans];  // local animation matrices
//			} ms3d_joint_t;
			
			var flags:int = _data.readByte();
			var name:String = _data.readMultiByte(MsJoint.name_length,"us-ascii");
			var parentName:String = _data.readMultiByte(MsJoint.parentName_length,"us-ascii");
			var rotation:Array = [_data.readFloat(),_data.readFloat(),_data.readFloat()];
			var position:Array = [_data.readFloat(),_data.readFloat(),_data.readFloat()];
			
			var numKeyFramesRot:int = _data.readShort();
			var numKeyFramesTrans:int = _data.readShort();
			
			var temp:Array;
			
			var rots:Array = [];
			for(var i:int=0; i < numKeyFramesRot; ++i)
			{
				temp = [_data.readFloat(),_data.readFloat(),_data.readFloat(),_data.readFloat()];
				rots.push(temp);
			}
			var trans:Array = [];
			for(var j:int=0; j < numKeyFramesRot; ++j)
			{
				temp = [_data.readFloat(),_data.readFloat(),_data.readFloat(),_data.readFloat()];
				trans.push(temp);
			}
			
			return new MsJoint(flags,name,parentName,rotation,position,numKeyFramesRot,numKeyFramesTrans,rots,trans);
		}
	}
}